package implicits

import akka.stream.scaladsl.Flow
import org.joda.time.DateTime
import play.api.http._
import play.api.http.websocket._
import play.api.libs.streams.AkkaStreams
import play.api.mvc.Codec
import play.api.mvc.WebSocket.MessageFlowTransformer
import upickle.default._

import scala.util.control.NonFatal


trait UjsonExtraTool {

  implicit def contentTypeOf_UJson(implicit codec: Codec): ContentTypeOf[ujson.Value] = {
    ContentTypeOf[ujson.Value](Some(ContentTypes.JSON))
  }

  implicit def writeableOf_UJson(implicit codec: Codec): Writeable[ujson.Value] = {
    Writeable(jsval => codec.encode(jsval.toString()))
  }

  implicit val uJsonMessageFlowTransformer: MessageFlowTransformer[ujson.Value, ujson.Value] = {
    def closeOnException[T](block: => T) =
      try {
        Left(block)
      } catch {
        case NonFatal(e) => Right(CloseMessage(Some(CloseCodes.Unacceptable), "Unable to parse json message"))
      }

    (flow: Flow[ujson.Value, ujson.Value, _]) => {
      AkkaStreams.bypassWith[Message, ujson.Value, Message](Flow[Message].collect {
        case BinaryMessage(data) => closeOnException(ujson.read(data.iterator.asInputStream))
        case TextMessage(text) => closeOnException(ujson.read(text))
      })(flow.map { json =>
        TextMessage(write(json))
      })
    }
  }


}
